<?php
/* © 2020-2025 ALYR.NET */
/**
 * 钉钉认证处理程序
 * 处理钉钉扫码登录的回调，验证用户身份
 */

// 在文件顶部添加详细错误报告
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// 启动会话
session_start();

// 设置内容类型
header('Content-Type: text/html; charset=utf-8');

// 引入钉钉配置文件
require_once __DIR__ . '/config/dingtalk.php';

// 检查回调参数
$code = $_GET['code'] ?? '';
$state = $_GET['state'] ?? '';

if (empty($code)) {
    $errorMsg = '错误: 未收到临时授权码，请重新尝试登录';
    log_dingtalk($errorMsg, 'error');
    echo "
    <script>
        alert('$errorMsg');
        window.location.href = 'login.php?error=auth_failed';
    </script>";
    exit;
}

// 验证state防止CSRF攻击
if (empty($_SESSION['dd_state']) || $state !== $_SESSION['dd_state']) {
    $errorMsg = '错误: 安全验证失败，请重新尝试登录';
    log_dingtalk('state验证失败: 会话state=' . ($_SESSION['dd_state'] ?? 'null') . ', 请求state=' . $state, 'error');
    echo "
    <script>
        alert('$errorMsg');
        window.location.href = 'login.php?error=auth_failed';
    </script>";
    exit;
}

// 清除会话中的state
unset($_SESSION['dd_state']);

// 输出调试信息到页面上（仅在调试模式下）
function debug_output($title, $data) {
    // 检查调试模式
    if (isset($_GET['debug']) && $_GET['debug'] === '1') {
        echo '<div style="margin: 20px; padding: 15px; border: 1px solid #ddd; background: #f8f9fa; font-family: monospace;">';
        echo '<h3 style="margin-top:0;">' . htmlspecialchars($title) . '</h3>';
        echo '<pre>' . htmlspecialchars(is_string($data) ? $data : json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)) . '</pre>';
        echo '</div>';
    }
}

try {
    // 1. 使用临时授权码获取用户token
    log_dingtalk('开始获取用户访问凭证，临时授权码：' . $code, 'info');
    
    $tokenUrl = get_dingtalk_config('api.tokenUrl');
    $tokenData = [
        'clientId' => get_dingtalk_config('appId'),
        'clientSecret' => get_dingtalk_config('appSecret'),
        'code' => $code,
        'grantType' => 'authorization_code'
    ];
    
    // 记录详细的请求参数
    log_dingtalk('Token请求参数: ' . json_encode($tokenData), 'info');
    
    // 使用备用接口进行额外保障
    if (empty($tokenUrl) || $tokenUrl !== 'https://api.dingtalk.com/v1.0/oauth2/userAccessToken') {
        $tokenUrl = 'https://api.dingtalk.com/v1.0/oauth2/userAccessToken';
    }
    
    $ch = curl_init($tokenUrl);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($tokenData));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Accept: application/json'
    ]);
    
    // 添加额外的CURL选项，以处理潜在的SSL问题
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    
    $tokenResponse = curl_exec($ch);
    $tokenHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);
    
    // 记录详细的调试信息
    log_dingtalk('Token请求状态码: ' . $tokenHttpCode . ', 响应: ' . substr($tokenResponse, 0, 500), 'info');
    if (!empty($curlError)) {
        log_dingtalk('CURL错误: ' . $curlError, 'error');
    }
    
    if ($tokenHttpCode !== 200) {
        $errorMsg = '错误: 获取访问凭证失败，请重新尝试登录';
        log_dingtalk('获取访问凭证失败: ' . $tokenResponse, 'error');
        if (isset($_GET['debug']) && $_GET['debug'] === '1') {
            // 在调试模式下，显示更详细的错误
            debug_output('Token获取失败', [
                'HTTP状态码' => $tokenHttpCode,
                '响应数据' => json_decode($tokenResponse, true) ?: $tokenResponse
            ]);
        } else {
            echo "
            <script>
                alert('$errorMsg');
                window.location.href = 'login.php?error=auth_failed';
            </script>";
            exit;
        }
    }
    
    $tokenData = json_decode($tokenResponse, true);
    
    if (!isset($tokenData['accessToken'])) {
        log_dingtalk('访问凭证响应格式错误: ' . $tokenResponse, 'error');
        header('Location: login.php?error=auth_failed');
        exit;
    }
    
    $accessToken = $tokenData['accessToken'];
    
    // 在获取token后添加
    if (isset($_GET['debug']) && $_GET['debug'] === '1') {
        // 设置更友好的页面样式
        echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">';
        echo '<title>钉钉授权调试</title>';
        echo '<link rel="stylesheet" href="assets/css/auth.css">';
        echo '</head><body>';
        echo '<h2>钉钉授权调试页</h2>';
        echo '<p>本页面显示授权过程中的详细信息，仅在调试模式下可见。</p>';
    }

    // 在tokenResponse获取后
    if (isset($_GET['debug']) && $_GET['debug'] === '1') {
        debug_output('获取访问凭证请求', [
            'URL' => $tokenUrl,
            '请求数据' => $tokenData,
            'HTTP状态码' => $tokenHttpCode,
            '响应数据' => json_decode($tokenResponse, true)
        ]);
    }
    
    // 2. 获取用户信息
    log_dingtalk('开始获取用户信息', 'info');
    
    $userInfoUrl = get_dingtalk_config('api.userInfoUrl');
    
    $ch = curl_init($userInfoUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'x-acs-dingtalk-access-token: ' . $accessToken,
        'Accept: application/json'
    ]);
    
    // 添加额外的CURL选项，以处理潜在的SSL问题
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    
    $userInfoResponse = curl_exec($ch);
    $userInfoHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);
    
    // 记录详细的调试信息
    log_dingtalk('用户信息请求状态码: ' . $userInfoHttpCode . ', 响应: ' . substr($userInfoResponse, 0, 500), 'info');
    if (!empty($curlError)) {
        log_dingtalk('CURL错误: ' . $curlError, 'error');
    }
    
    if ($userInfoHttpCode !== 200) {
        log_dingtalk('获取用户信息失败: ' . $userInfoResponse, 'error');
        header('Location: login.php?error=auth_failed');
        exit;
    }
    
    $userInfo = json_decode($userInfoResponse, true);
    
    if (!isset($userInfo['unionId'])) {
        log_dingtalk('用户信息响应格式错误: ' . $userInfoResponse, 'error');
        header('Location: login.php?error=auth_failed');
        exit;
    }
    
    if (!isset($userInfo['unionId']) || empty($userInfo['unionId'])) {
        log_dingtalk('非企业成员，缺少unionId', 'warning');
        header('Location: login.php?error=unauthorized');
        exit;
    }
    
    // 记录用户登录信息
    $_SESSION['dd_user_id'] = $userInfo['unionId'];
    $_SESSION['dd_user_name'] = $userInfo['nick'] ?? ($userInfo['name'] ?? '用户');
    $_SESSION['dd_user_avatar'] = $userInfo['avatarUrl'] ?? '';
    $_SESSION['user_logged_in'] = true;
    $_SESSION['login_time'] = time();
    
    // 记录登录成功日志
    $userName = $_SESSION['dd_user_name'];
    log_dingtalk("用户 {$userName} 登录成功", 'success');
    
    // 重定向到首页或之前尝试访问的页面
    $redirect = $_SESSION['login_redirect'] ?? 'index.php';
    unset($_SESSION['login_redirect']);
    
    // 在userInfoResponse获取后
    if (isset($_GET['debug']) && $_GET['debug'] === '1') {
        debug_output('获取用户信息请求', [
            'URL' => $userInfoUrl,
            'AccessToken' => substr($accessToken, 0, 10) . '...',
            'HTTP状态码' => $userInfoHttpCode,
            '响应数据' => json_decode($userInfoResponse, true)
        ]);
        
        // 最后添加调试页面底部
        echo '<p style="margin-top:30px;text-align:center;"><a href="login.php" style="color:#4285f4;text-decoration:none;">返回登录页</a></p>';
        echo '</body></html>';
        exit; // 在调试模式下不执行后续重定向
    }
    
    header("Location: {$redirect}");
    exit;
    
} catch (Exception $e) {
    log_dingtalk('认证过程发生异常: ' . $e->getMessage(), 'error');
    header('Location: login.php?error=auth_failed');
    exit;
}